#include <unistd.h>
#include <cerrno>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <sys/poll.h>
#include <sys/epoll.h>
#include <net/if.h>
#include <sys/ioctl.h>

#include "dataDevice.h"
#include "unp.h"
#include "network.h"
#include "signal.h"

using namespace std;

void sig_brokenPipe(int signo)
{
  cout<<"Broken pipe"<<endl;
}

dataDevice* openDataDevice()
{
	dataDevice *device = NULL;
	while(true)
	{
		if(device)
		{
			delete device;
			device = NULL;
		}

		/* create device */
		//device = new ethernetDataDevice("127.0.0.1", 50000); 
		device = new ethernetDataDevice("192.168.2.1", 50000); 

		/* open device */
		if(device->open())
			return device;

		sleep(5);
		cout<<"Reconneting...."<<endl;
	}

	return NULL;
}

int main(int argc, char **argv)
{
	Signal(SIGPIPE, sig_brokenPipe);
	int res;

	dataDevice *gateWayDevice = NULL;
	//dataDevice *coordinate = new serialDataDevice("/dev/ttyS3", "115200");
	dataDevice *coordinate = new serialDataDevice("/dev/ttyTX0", "115200");
	coordinate->open();

	char buff[65535];

	while(true)
	{
		if(!gateWayDevice)
		{
			gateWayDevice = openDataDevice();
			continue;
		}

		cout<<"*"<<endl;

		struct pollfd fds[2];
		//gateWay
		fds[0].fd = gateWayDevice->getFd();
		fds[0].events = POLLIN;
		cout<<"**"<<endl;


		fds[1].fd = coordinate->getFd();
		cout<<"fds[1].fd "<<fds[1].fd<<endl;
		fds[1].events = POLLIN;
		
		cout<<"***"<<endl;


		while(true)
		{
			res = TEMP_FAILURE_RETRY(poll(fds, 2, -1));
			if(res == 0)
			{
				cout<<"Node: Select timeout"<<endl;
				continue;
			}

			if(fds[0].revents & POLLIN)	//Read data from gateway
			{
				bzero(buff, sizeof(buff));
				res = recv(fds[0].fd, buff, sizeof(buff), 0);
				cout<<"Node: Read "<<res<<" from gateway."<<endl;
				if(res == 0)
				{
					cout<<"Node: Socket closed by gateway"<<endl;
					break;
				}
				else if(res < 0)
				{
					if(errno == EINTR)
						continue;

					cout<<"Node: Read error from gateway"<<endl;
					break;
				}
				else if(res > 0)
				{
					cout<<"Node: recv "<<res<<" bytes from gateway"<<endl;
					/*
					for(int i=0;i<res;i++)
						printf("\\x%02x ", buff[i]);
					cout<<endl;
					*/
					/***** write to device*********/
					int wres = coordinate->write(buff, res);
					cout<<"Write to "<<wres<<" to device"<<endl;
					/***** write to device end *********/

				}
			}

			if(fds[1].revents & POLLIN)	//Read data from device
			{
				bzero(buff, sizeof(buff));
				/***** read from device*******/
				//cout<<"Read from device......."<<endl;
				int res = coordinate->read(buff, sizeof(buff));
				cout<<"Node: Read "<<res<<" bytes from device"<<endl;
				if(res > 0)
				{
					//cout<<"Read "<<res<<" bytes from device"<<endl;
					/***** read from devicr end *******/

					/**** send data to gateway ******/
					for(int i = 0;i<res;i++)
						printf("%02hhx ", buff[i]);
					cout<<endl;
					res = send(fds[0].fd, buff, res, 0);
					cout<<"Send to gateway: "<<res<<" OK"<<endl;
					
					if(res<0)
						perror("send to gateway");

					/**** send data to gateway end ******/
				}
			}//if(fds[1].revents & POLLIN) //Read data from device
		}
		
	
		if(gateWayDevice)
		{
			delete gateWayDevice;
			gateWayDevice = NULL;
		}

	}//end while(true)
	if(coordinate)
	{
		delete coordinate;
		coordinate = NULL;
	}

	return 0;
}//end main
